#ifndef OPTIMISEUREQUIPEMENT_HPP
#define OPTIMISEUREQUIPEMENT_HPP

// Créé avec XmlCppClassGenerator version 2.0.

#include "Utils/BiClef.hpp"
#include "XmlInfo/XmlInfoContrat.hpp"
#include "XmlInfo/XmlInfoMonstre.hpp"

#include <QHash>
#include <QList>
#include <QMultiMap>

class CalculateurReussite;

namespace Invisible
{
    class BonusEquipement;
}

/** Classe qui détermine l'équipement optimal pour le monstre.
  *
  * L'équipement optimal est l'équipement qui permet d'obtenir le pourcentage
  * de réussite minimal tout en minimisant les coûts. A priori on va  favoriser
  * le choix d'un équipement permanent, pour amortir les coûts.
  *
  * @author Johan "Solo" Luisier
  * @date Juin 2012
  */
class OptimiseurEquipement
{
public:
  /** Constructeur
   *
   * Déclenche l'appel à initMembresStatiques pour initialiser correctement les
   * différents membres statiques de la classe.
   */
  OptimiseurEquipement();
  /** Destructeur
   *
   * Le destructeur libère la mémoire allouée pour le calculateur de réussite.
   */
  virtual ~OptimiseurEquipement();
  /** Opérateur qui réalise l'optimisation de l'équipement pour le contrat et le
   * monstre donné.
   *
   * On commence par copier les informations du contrat et du monstre dans les
   * membres ValeursContrat et ValeursMonstre, qui pourront être modifiées.
   *
   * Le but est de trouver l'équipement le meilleur marché qui permet
   * d'atteindre le pourcentage de réussite minimal imposé dans les préférences.
   *
   * @return un pointeur sur l'équipement optimal s'il existe, ou @c 0 si le
   * monstre peut déjà remplir le contrat avec le pourcentage minimal requis.
   */
  const QList< unsigned >* operator()( const XmlInfoContrat& contrat,
                                       const XmlInfoMonstre& monstre );
  protected:
  /** Méthode qui joue le rôle de fonction de rappel (@e callback) pour le
   * template fournissant les combinaisons d'équipement.
   *
   * Pour chaque combinaison, passée en argument par le biais des itérateurs
   * @c debut et @c fin, on calcule le pourcentage de réussite et le coût.
   * Ces deux grandeurs sont utilisées comme clés dans la @c QMultiMap qui
   * stocke l'équipement.
   *
   * @param[in] debut itérateur pointant sur le premier élément de la
   * combinaison courante.
   * @param[in] fin itérateur pointant sur la fin de la combinaison courante.
   */
  void traiteEquipement( const QList< unsigned >::iterator &debut,
                         const QList< unsigned >::iterator &fin );
  /** Méthode qui détermine l'équipement optimal d'après le pourcentage de
   * réussite et le coût total.
   *
   * Si aucun équipement ne permet d'atteindre le seuil de réussite minimal,
   * on renvoie alors l'équipement donnant le meilleur taux de réussite pour le
   * moindre coût.
   *
   * @return une référence constante sur l'équipement déterminé comme étant
   * optimal.
   */
  const QList< unsigned >& trouveEquipementOptimal() const;
  /** Copie locale du contrat.
   *
   * On utilise un pointeur car le constructeur par défaut n'est pas accessible.
   */
  XmlInfoContrat * ValeursContrat;
  /** Copie locale du monstre.
   *
   * On utilise un pointeur car le constructeur par défaut n'est pas accessible.
   */
  XmlInfoMonstre * ValeursMonstre;
  /** Contient les équipements (temporaires et permanents) pouvant être utilisés
    * par le monstre.
    */
  QList< unsigned > EquipementPossible;
  /** Tableau associatif liant l'équipement à une probabilité et un coût.
    *
    * Le choix d'un conteneur ordré permet d'obtenir facilement l'équipement
    * donnant la probabilité de réussite voulue avec un coût minimum.
    */
  QMultiMap< BiClef, QList< unsigned > > EvalutationEquipement;
  /** Instance de calcul des probabilités.
    */
  CalculateurReussite * Calculateur;
private:
  /** Utilisation de la classe BonusEquipement.
    */
  typedef Invisible::BonusEquipement Bonus;
  /** Initialise la liste des équipements existants.
    *
    * Il n'est pas possible d'initialiser un membre @c static et @c const s'il
    * son type est un conteneur propre à Qt. Il faut donc ruser et créer une
    * méthode qui réalise l'initialisation.
    */
  static void initMembresStatiques();
  /** Contient la liste des équipement de monstre pouvant être créés dans
    * l'atelier.
    *
    * Les objets sont identifiés par leur identifiant tel que définit dans le
    * fichier XML fourni èar l'API.
    */
  static QHash< unsigned, Bonus > EquipementExistant;
  /** Contient la valeur minimale pour la probabilité de réussite du contrat.
    *
    * Est lu depuis les préférences.
    */
  static unsigned SeuilReussite;
};


#endif // OPTIMISEUREQUIPEMENT_HPP
